package 抽象语法树遍历器;

import 抽象语法树类.*;
import 抽象语法树类.表达式类.实例化表达式;
import 抽象语法树类.语句类.函数调用语句;
import 符号表和作用域.*;

public class 符号定义器 extends 抽象语法树监听器 {

    public 符号表 符号表;
    public 作用域 当前作用域;

    private void Log(String log) {
        System.out.println(log);
    }

    @Override
    public void 进入程序节点(程序节点 程序节点) {
        符号表 = new 符号表();
        符号表.全局作用域 = new 全局作用域();
        Log("创建全局作用域");

        当前作用域 = 符号表.全局作用域;
        程序节点.绑定(当前作用域);
        Log("进入全局作用域");
    }

    @Override
    public void 离开程序节点(程序节点 程序节点) {
        当前作用域 = null;
        Log("离开全局作用域");
    }

    @Override
    public void 进入结构体定义(结构体定义 结构体定义) {
        var 结构体 = new 结构体符号(结构体定义.结构体名, 当前作用域);
        当前作用域.定义(结构体);
        结构体定义.绑定(结构体);

        当前作用域 = 结构体;
        Log("进入结构体作用域");
    }

    @Override
    public void 离开结构体定义(结构体定义 结构体定义) {
        当前作用域 = 当前作用域.取外围作用域();
        Log("离开结构体作用域");
    }

    @Override
    public void 进入函数定义(函数定义 函数定义) {
        var 函数符号 = new 函数符号(函数定义.函数名, 当前作用域);
        当前作用域.定义(函数符号);
        Log("定义函数：" + 函数定义.函数名);
        函数定义.绑定(函数符号);
        函数符号.代码块 = 函数定义.代码块;
        
        当前作用域 = 函数符号;
        Log("进入函数作用域");
    }

    @Override
    public void 离开函数定义(函数定义 函数定义) {
        当前作用域 = 当前作用域.取外围作用域();
        Log("离开函数作用域");
    }

    @Override
    public void 进入代码块(代码块 代码块) {
        var 局部作用域 = new 局部作用域(当前作用域);
        当前作用域 = 局部作用域;
        代码块.绑定(局部作用域);
        Log("进入局部作用域");
    }

    @Override
    public void 离开代码块(代码块 代码块) {
        当前作用域 = 当前作用域.取外围作用域();
        Log("离开局部作用域");
    }

    @Override
    public void 进入变量定义(变量定义 变量定义) {
        var 变量符号 = new 变量符号(变量定义.变量名);
        当前作用域.定义(变量符号);
        Log("定义变量：" + 变量定义.变量名);
    }

    @Override
    public void 进入实例化表达式(实例化表达式 实例化表达式) {
        实例化表达式.作用域 = 当前作用域;
    }

    @Override
    public void 进入函数调用语句(函数调用语句 函数调用语句) {
        函数调用语句.作用域 = 当前作用域;
    }
}
